#include "Portfolio.h"
#include "State.h"
#include "NullState.h"
#include "IntroFadeState.h"

volatile int Portfolio::ticks = 0;
volatile int Portfolio::game_time = 0;

using namespace std;

void Portfolio::ticker()
{
	ticks++;
}
END_OF_FUNCTION(ticker)

void Portfolio::game_time_ticker()
{
	game_time++;
}
END_OF_FUNCTION(game_time_ticker)


Portfolio::Portfolio() : updates_per_second(60)
{ 
	cout<<"Portfolio starting."; 
	nextState = NULL;
	currentState = new NullState();
	currentState->port = this;
	quit = false;
	stateChanged = false;
}

// Setup the allegro library
void Portfolio::setupAllegro()
{
	allegro_init();
	install_keyboard();
	install_mouse();
	install_timer();
	install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);

	LOCK_VARIABLE(ticks);
	LOCK_FUNCTION(ticker);
	install_int_ex(Portfolio::ticker, BPS_TO_TIMER(updates_per_second));

	LOCK_VARIABLE(game_time);
	LOCK_FUNCTION(game_time_ticker);
	install_int_ex(Portfolio::game_time_ticker, BPS_TO_TIMER(10));//i.e. game time is in tenths of seconds

	int ret = 0;
	int bpp = 0;
	if (bpp > 0) {
		/* set a user-requested color depth */
		set_color_depth(bpp);
		ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
	}
	else {
		/* autodetect what color depths are available */
		static int color_depths[] = { 32, 24, 16, 15, 0 };
		for (int a = 0; color_depths[a]; a++) {
			bpp = color_depths[a];
			set_color_depth(bpp);
			ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
			if (ret == 0)
				break;
		}
	}

	/* did the video mode set properly? */
	if (ret != 0) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("Error setting %d bit graphics mode\n%s\n", bpp,
			allegro_error);
		return;
	}

	show_mouse(screen);

	/* specify that images should be loaded in a truecolor pixel format */
	set_color_conversion(COLORCONV_TOTAL);

	//Set text mode
	text_mode(-1);

	rMgr = new ResourceManager();
	rMgr->loadGlobalResources();

	// Setup graphics util
	gUtil = new GraphicsUtil();
	
}

void Portfolio::startGUI()
{
	int fps = 0, frames_done = 0, old_time = 0;

	//an array to store the number of frames we did during the last 10 tenths of a second
	int frames_array[10]; 

	//used to store the index of the last updated value in the array
	int frame_index = 0;

	for(int ii = 0; ii < 10; ii++)
	{
		frames_array[ii] = 0;//initialize the array to 0
	}

	while(!key[KEY_ESC] && !quit)
	{
		while(ticks == 0)
		{
			rest(100 / updates_per_second);
		}

		while(ticks > 0)
		{
			int old_ticks = ticks;

			// Do logic
			currentState->update(0.3f);

			ticks--;
			if(old_ticks <= ticks)
			{
				break;
			}
		}

		//i.e. a 0.1 second has passed since we last counted the frames
		if(game_time >= old_time + 1)
		{
			//decrement the fps by the frames done a second ago
			fps -= frames_array[frame_index];

			//store the number of frames done this 0.1 second
			frames_array[frame_index] = frames_done;

			//increment the fps by the newly done frames
			fps += frames_done;

			//increment the frame index and snap it to 10
			frame_index = (frame_index + 1) % 10;

			frames_done = 0;
			old_time += 1;
		}

		acquire_screen();
		currentState->render();
		release_screen();
		frames_done++;//we drew a frame!

		if (stateChanged)
		{
			actualStateChange();
		}
		Sleep(0);
	}

	cleanUp();
}

void Portfolio::cleanUp()
{
	delete rMgr;
	delete gUtil;
}

void Portfolio::changeState(State *newState)
{
	stateChanged = true;
	nextState = newState;
}

void Portfolio::actualStateChange()
{
	stateChanged = false;
	currentState->leave();
	currentState->port = NULL;
	delete currentState;
	currentState = NULL;

	nextState->port = this;
	nextState->enter();
	currentState = nextState;
}